<template>
  <!-- 表格上方提示信息（默认样式） -->
  <div v-if="props.tableHeaderTips" class="zs-text-gray-dark zs-space-bottom zs-text-sm">
    <span v-for="item,index in props.tableHeaderTips" :key="index" class="zs-space-right-bg">{{item}}</span>
  </div>

  <!-- 表格上方提示信息插槽（自定义样式） -->
  <slot name="topTip" />

  <!-- 主体表格 -->
  <!-- :style="{'max-height':tableHeight ? 'none' : `calc(100vh - ${props.maxHeight}px`}" -->
  <el-table
    class="zs-table-page-main"
    :max-height="`calc(100vh - ${props.maxHeight}px)`"
    :row-key="rowKey || 'id'"
    v-loading="loading"
    ref="publicTable"
    id="my-table"
    :stripe="stripe"
    :data="list"
    @selection-change="handleSelectionChange"
    :default-expand-all="defaultExpandAll"
    :default-sort="defaultSort"
    :row-class-name="rowClassName"
    :span-method="spanMethod"
    :header-cell-style="headerCellStyle"
    :expand-row-keys="expandedRowKeys"
    :cell-class-name="cellClassName"
    :header-cell-class-name="setHeaderCellClass"
    @sort-change="curSortChange"
  >
    <!--选择框-->
    <el-table-column class-name="table-select" reserve-selection v-if="isCheckBox" type="selection" align="center" width="26" :selectable="defaultDisabledCheckbox">
    </el-table-column>
    <el-table-column class-name="table-select" v-if="isRadio" align="center" width="26">
      <template #default="scope">
        <el-radio :disabled="props.radioDisabledFn ? props.radioDisabledFn(scope) : radioDisabled" @click.stop.prevent="switchRadioStatus($event,scope)" v-model="curSelectRadio.row[radioMark]" :label="scope.row[radioMark]" size="large" />
      </template>
    </el-table-column>

    <!---seq 序列号--->
    <!-- <el-table-column
      :fixed="props.indexFixed"
      v-if="!isHaveIndex"
      type="index"
      label="序号"
      width="60"
      :align="'center'"
    /> -->

    <!---自定义序列号--->
    <el-table-column :fixed="indexFixed" v-if="isHaveIndex" :label="indexLabel" width="80" :align="indexAlign">
      <template #default="scope">
        {{ scope.$index + 1 + page.pageSize * (page.current - 1) }}
        <!-- <span>999999</span> -->
      </template>
    </el-table-column>

    <!--数据列-->
    <el-table-column
      v-for="item in cloumns"
      :key="item.prop"
      :prop="item.prop"
      :label="item.label"
      :width="item.width"
      :min-width="item.minWidth"
      :align="item.align || 'center'"
      :show-overflow-tooltip="!item.isNotooltip"
      :fixed="item.fixed"
      :sortable="item.sortable || false"
      :sort-method="item.sortMethod"
      :sort-by="item.sortBy"
      :sort-orders="item.sortOrders"
      :filters="item.filterList"
      :filter-method="item.filterMethod"
    >
      <!-- 自定义表头 -->
      <template v-if="item.HeaderRender" #header>
        <hsTableRender :render="item.HeaderRender()"></hsTableRender>
      </template>
      <!-- 排序自定义表头实现多列排序 -->
      <template v-else-if="item.sort" #header>
        <span>{{ item.label }}</span>
          <span :class="{'isAsc':curSortColumns.sortData[item.prop] == 'asc','isDesc':curSortColumns.sortData[item.prop] == 'desc'}" class="caret-wrapper">
            <i @click="tableSortFn(item,'asc')" class="sort-caret ascending"></i>
            <i @click="tableSortFn(item,'desc')" class="sort-caret descending"></i>
          </span>
      </template>
      <template #default="scope">
        <!-- 示例 参考下方 testColumns -->
        <!-- html可使用渲染函数自定义渲染html -->
        <template v-if="item.type === 'html'">
          <hsTableRender v-if="item.render && scope.$index !== -1" :render="item.render(scope)"></hsTableRender>
          <span v-else>-</span>
        </template>

        <!-- 字典转换 --->
        <!-- 
          currentDict  当前转换的字典数据
          dictField    当前字典取值字段
          valField     当前内容在字典中的字段
          currentClass 当前需要显示的文字类名(function返回动态类名)
        -->
        <!-- currentDict建议传以当前字段为键名的对象  若是传数组需要传递比对字段如valField:‘dictValue’ -->
        <template v-else-if="item.type === 'dict' && item.currentDict">
            <!-- :class="{'zs-text-green': item.isHaveClass && scope.row[item.prop] == item.green,'zs-text-red': item.isHaveClass && scope.row[item.prop] == item.red,}" -->
          <span
            :class="item.isHaveClass ? item.currentClass(scope.row) : ''"
          >
            {{ converDict(scope.row[item.prop], item.currentDict, item.multiple, item.dictField, item.valField) }}
          </span>
        </template>

        <!-- 日期格式 dateFormat格式化方式默认'yyyy-mm-dd' dateType转换类型默认singlesingle单个转换multiple多个转换  dateIntervalSymbol多个转换时拼接的字符默认‘~’ -->
        <template v-else-if="item.type === 'date'">
          <span>
            {{ convertDate(scope.row, item.prop, item.dateFormat, item.dateType, item.dateIntervalSymbol) }}
          </span>
        </template>

        <!-- 图片url -->
        <template v-else-if="item.type === 'image'">
          <img
            v-if="scope.row[item.prop]"
            :src="scope.row[item.prop]"
            alt=""
            class="table-img"
          />
          <span v-else>-</span>
        </template>

        <!-- 特殊处理自定义显示方法的显示数据传递function -->
        <span :class="item.isHaveClass ? item.currentClass(scope.row) : ''" v-else-if="item.type == 'customMethods'">{{item.methods(scope.row,emptyMark,scope)}}</span>
        <!-- 正常取值显示值无内容默认显示‘-’或者自定义 -->
        <span v-else :class="item.isHaveClass ? item.currentClass(scope.row) : ''">{{scope.row[item.prop] ? scope.row[item.prop] : (item.emptyContent || emptyMark)}}</span>

      </template>
    </el-table-column>

    <!--自定义数据列插槽如操作列-->
    <slot name="column" />
  </el-table>

  <!-- 默认样式的表格下方单位展示 -->
  <div class="zs-text-gray-dark zs-text-sm zs-space-top" v-for="item in props.tableTips" :key="item">{{item}}</div>

  <!-- 自定义样式的表格下方单位展示 -->
  <slot name="bottomTip" />

  <!-- 分页 -->
  <div v-if="isHavePage" class="zs-pagination zs-space-top-sm zs-table-page-pagination">
    <el-pagination
      v-model:currentPage="page.current"
      v-model:page-size="page.pageSize"
      :page-sizes="curPageSizes"
      :small="true"
      :background="true"
      layout="total, sizes, prev, pager, next, jumper"
      :total="page.total"
      @size-change="handleSizeChange"
      @current-change="handleCurrentChange"
    />
  </div>
</template>

<script setup>
/**
* @testColumns  各类型转换示例
* @resolveComponent 按名称手动解析已注册的组件,如果你可以直接引入组件就不需使用此方法
* @render 渲染函数的使用请参考vue文档 https://cn.vuejs.org/guide/extras/render-function.html
let testColumns = [
// 普通字典取值
{
  type:'dict',
  currentDict:ENTERPRISE_STATUS_id,
  dictField:'dicName'
},
// 带类名的字典取值
{
  type:'dict',
  currentDict:auditDict,
  isHaveClass:true,
  currentClass:(row)=>{ return {'zs-approval-status-wait':row['auditState'] == 0,'zs-approval-status-yes':row['auditStatus'] == 1,'zs-approval-status-no': row['auditStatus'] == 9}}
},
// 日期类型---单个dateFormat默认{y}-{m}-{d}
{type:'date',dateFormat:"{y}-{m}-{d} {h}:{i}:{s}"},
// 日期类型---多个
{prop:'date1,date2',type:'date',dateType:'multiple',dateIntervalSymbol:'~'},
// 需要处理后显示的类型 empty为空时显示的内容统一处理
{
  type:'customMethods',
  methods:(row,empty)=>row.firstBizTypeInfo ? row.firstBizTypeInfo.dicName : empty
}
// render函数自定义渲染类型
{ type:'html',
  // createElement 方式 
  render:(scope)=>{
    const elInput = resolveComponent('elInput')
    return h(elInput,{'modelValue':scope.row.companyName,
      "onUpdate:modelValue": (val) => {
        // 实现了数据更新
        scope.row.companyName = val
        return scope.row.companyName
      }
    })
  },
  // JSX方式
  render:(scope)=>{
    return return <el-input v-model={scope.row.companyName} on-change={()=>{}}></el-input>
  }
},
]
*/
// import TableRender from "./table-render.vue"
import { ref, reactive, watch, nextTick } from "vue";
import { useStore } from "vuex";
import { parseTime } from '@/utils/publicUtils';
let store = useStore();
const curPageSizes = ref(store.state.uiPageSizes);
const curPageSize = ref(store.state.uiPageSizeDefault);
// 父组件传递内容
const props = defineProps({
rowKey:{ type: String },
// tableHeight:{ type:[String,Number] },
loading:{ type: Boolean, default: false },
// 最大高度
maxHeight:{type: Number,default: 240},
// 是否有序号
isHaveIndex: { type: Boolean, default: true },
// 数据列
cloumns: {
  type: Array,
  default: () => []
},
// 表格数据
tableData: {
  type: Array,
  default: () => []
},
// 总条数
total: {
  type: Number,
  default: 0
},
// 是否自定义序号
indexFixed:{type: [Boolean,String], default:false},
// 表格下方单位提示
tableTips:{
  type:Array,
},
// 表格头部提示
tableHeaderTips:{
  type:[Array,Boolean],
},
// 是否开启选择
isCheckBox:{type: Boolean, default:false},
// 是否拥有分页
isHavePage:{type: Boolean, default:true},
// 是否单选
isRadio: {type:Boolean},
// 单选标识(可能会是id也可能会是其他字段)
radioMark: {type:String,default:'id'},
// 单选数据
selectRadio: { type: Object },
// 单选禁用
radioDisabled: { type: Boolean },
// 单选自定义禁用方法
radioDisabledFn: { type: Function },
// 树形数据是否默认展开
defaultExpandAll:{ type:Boolean },
// 序号label
indexLabel:{type:String,default:'序号'},
// 序号方向
indexAlign:{type:String,default:'center'},
// 为表格添加类名方法
rowClassName: { type: [Function,String] },
// 为表格添加类名方法
cellClassName: { type: [Function,String] },
// 是否开启斑马纹默认开启
stripe: { type: Boolean, default: true },
// 设置排序方法
defaultSort: { type: Object },
// 设置合并列或行方法
spanMethod: { type: Function },
// 设置表头样式的方法
headerCellStyle: { type: Function },
// 默认展开的节点
expandedRowKeys: { type: Array },
// 默认页条数
defaultPageSize: { type: [Number, String], default: 0 },
// 多选表格时定义表格是否禁止选中
selectable: { type: Function },
// 表头样式
headerCellClass: { type: [String, Function] },
// 禁用多选
disabledCheckbox: { type: Boolean, default: false }
});
// let tableHeight = ref(document.body.clientHeight - props.maxHeight)
const emits = defineEmits(['pageChange','handleSelectionChange','update:selectRadio','sortChange','onSortChange']);

// 表格Ref
let publicTable = ref()
// 列表数据
let list = ref(props.tableData);
// 分页数据
let page = reactive({
current: 1,
pageSize: Number(props.defaultPageSize) || curPageSize.value,
total: 0,
});
watch(
[() => props.tableData,()=>props.total],
(newVal) => {
  list.value = newVal[0];
  page.total = newVal[1];
},
// {immediate:true,deep:true}
)
if (props.isRadio) {
watch(()=>props.selectRadio,(newVal=>{
  curSelectRadio.row = newVal
}))
}
let emptyMark = '-'
// 字典转换
/**
* @currentDict  当前转换的字典数据
* @dictField    当前字典取值字段
* @valField     当前内容在字典中的字段
* @multipe      flg是否多选 splitMark转换数组标识 joinMark转换字符串标识
*/
function converDict (val,currentDict,multiple = {},labelField = 'dictLabel',valField) {
if (!val && val !== 0) {
  return emptyMark;
}
let dictType = Object.prototype.toString.call(currentDict)
if (dictType == '[object Object]') {
  let labelArr = (multiple.flg ? (typeof(val) == 'string' ? val.split(multiple.splitMark || ',') : val) : [val]).map(itemVal => currentDict[String(itemVal)]?.[labelField] || emptyMark);
  return labelArr.join(multiple.joinMark || ',')
}
if (dictType == '[object Array]' && currentDict.length > 0) {
  let dictObj = {}
  let curData
  currentDict.forEach(itemDict=>{
    dictObj[valField] = itemDict
    if (itemDict[valField] == val) {
      curData = itemDict
    }
  })
  return curData?.[labelField] || (multiple.flg ? (typeof(val) == 'string' ? val.split(multiple.splitMark || ',') : val).map(itemVal => dictObj[String(itemVal)]?.[labelField] || emptyMark).join(multiple.joinMark || ',') : emptyMark);
} else {
  return '传递的数据为空'
}
}

// 日期转换
function convertDate (row,prop,format = "{y}-{m}-{d}",dateType = 'single',dateIntervalSymbol = '~') {
if (dateType == 'single') {
  // 单个日期转换
  return row[prop] ? parseTime(row[prop], format) : "-"
} else {
  // 区间日期转换
  return converIntervalDate(row,prop,format,dateIntervalSymbol)
}
}
// 区间日期转换
function converIntervalDate (row,prop,format = "{y}-{m}-{d}",dateIntervalSymbol) {
let fields = prop.split(',')
let dateStringArr = []
let flg = true
for (var i = 0; i < fields.length; i++) {
  if (!row[fields[i]]) {
    flg = false
    break;
  } 
  dateStringArr.push(parseTime(row[fields[i]], format))
}
return flg ? dateStringArr.join(dateIntervalSymbol) : emptyMark
}

// // 数字转换
// function numberCell(row,prop, isFormat, digit = 2){
// if (!row[prop] && row[prop] !== 0) {
//   return emptyMark
// }
// let curVal = Number(row[prop]).toFixed(digit)
// if (isFormat) {
//   return splitFormat(curVal)
// } else {
//   return Number(row[prop])
// }
// }

// 多行选中
function handleSelectionChange (val) {
emits('handleSelectionChange', val)
}

// 分页变化
function handleSizeChange () {
page.current = 1
emits('pageChange',page)
}
// 分页变化
function handleCurrentChange () {
emits('pageChange',page)
}

// 表格单选
let curSelectRadio = reactive({
row:{...props.selectRadio}
})
// 切换单选状态
function switchRadioStatus (e,scope) {
let { row } = scope
let isDisabled = e.target.parentNode.querySelector('.el-radio__original').disabled
if (isDisabled) {
  return 
}
// if (props.radioDisabled || props.radioDisabledFn(scope)) {
//   return 
// }
if (row[props.radioMark] == curSelectRadio.row[props.radioMark]) {
  curSelectRadio.row = {}
} else {
  curSelectRadio.row = {...row}
}
emits("update:selectRadio",curSelectRadio.row)
}

// 重置分页
function restPage () {
page.current = 1
page.pageSize = curPageSize.value
}

// 设置多选选中
function multipleSelected (val) {
if (!props.isCheckBox || Object.prototype.toString.call(val) !== '[object Array]') {
  throw Error('multipleSelected function params is not Array or Table isCheckBox is not true')
}
nextTick(() => { 
  val.forEach(el=>{
    publicTable.value?.toggleRowSelection(el)
  })
  list.value = list.value.map(el=>el)
})
}
// 设置默认是否禁用多选
function defaultDisabledCheckbox(row, index) {
if (props.selectable) {
  return props.selectable(row, index)
} else {
  return !props.disabledCheckbox
}
}
// 禁用多选时设置表头样式
function setHeaderCellClass(data) {
if (props.headerCellClass) {
  return props.headerCellClass(data)
} else if (props.disabledCheckbox && data.columnIndex === 0) {
  return 'disabled-checkbox'
}
}

function curSortChange(val) {
emits('sortChange',val)
}


let curSortColumns = reactive({
sortData:{}
})
function tableSortFn(curSort,val) {
if (curSortColumns.sortData[curSort.prop] && curSortColumns.sortData[curSort.prop] == val) {
  delete curSortColumns.sortData[curSort.prop]
} else {
  curSortColumns.sortData[curSort.prop] = val
}
let curSortArr = []
props.cloumns.forEach(el=>{
  if (curSortColumns.sortData[el.prop]) {
    curSortArr.push({prop:el.prop,type:curSortColumns.sortData[el.prop]})
  }
})
emits('onSortChange',curSortArr)
}

defineExpose({ publicTable,restPage,multipleSelected })
</script>

<script>
export default { name: "hsPageTable" }
</script>

<style lang="scss" scoped>
#my-table :deep(th.el-table__cell){
background: #f5f4f5;
}
.el-radio.el-radio--large {
height: auto;
}
#my-table :deep(.table-select .cell){
padding-right: 0 !important;
}
#my-table :deep(.disabled-checkbox .cell) {
  display: none;
}
#my-table :deep(.isAsc){
.ascending{
  border-bottom-color: #409eff;
}
}
#my-table :deep(.isDesc){
.descending{
  border-top-color: #409eff;
}
}
</style>